#include <iostream>
#include <initializer_list>
using namespace std;



template<class T>
T _min(T const& a, T const& b)
{
	if (a < b)
		return a;
	return b;
}

template<int m, int n, class Real, int size=m*n>
struct FMatrix
{
	Real v[m][n];
	FMatrix() { makeZero(); }
	FMatrix(std::initializer_list<Real>const& values) {
		int i = 0;
		makeZero();
		for (auto iter = values.begin(); i < size && iter != values.end(); ++iter, ++i)
			v[0][i] = *iter;
	}
	
	static FMatrix<m, n, Real> zero() { return FMatrix<m,n,Real>(); }
	static FMatrix<m, n, Real> one() {
		FMatrix<m, n, Real> one;
		one.makeIdentity();
		return one;
	}

	Real& operator()(int i, int j) { return v[i][j]; }
	const Real& operator()(int i, int j) const { return v[i][j]; }

	void makeZero()
	{
		for (int i = 0; i < m; ++i)
			for (int j = 0; j < n; ++j)
				v[i][j] = (Real)0;
	}
	void makeIdentity()
	{
		makeZero();
		for (int i = 0, s = _min(m, n); i < s; ++i)
			v[i][i] = (Real)1;
	}
};

typedef double Real;
#define Mat22d FMatrix<2, 2, Real>
#define Mat33d FMatrix<3, 3, Real>

template<class Real>
Real Determinant(Mat22d const& A)
{
	return A(0, 0) * A(1, 1) - A(0, 1) * A(1, 0);
}

template<class Real>
Real Determinant(Mat33d const& A)
{
	return A(0, 0) * (A(1, 1) * A(2, 2) - A(1, 2) * A(2, 1)) -
		A(0, 1) * (A(1, 0) * A(2, 2) - A(1, 2) * A(2, 0)) +
		A(0, 2) * (A(1, 0) * A(2, 1) - A(1, 1) * A(2, 0));
}

int main()
{
	auto A = Mat33d::one();
	cout << Determinant(A) << endl;
	cout << Determinant(Mat33d()) << endl;
	A(0, 1) = 2;
	A(1, 0) = -2;
	cout << Determinant(A) << endl;

	Mat33d B{ 8, -2, -3,
		      -2, 8, -3,
		      -3, -3, 3
	};
	cout << Determinant(B) << endl;

	return 0;
}

int main2()
{
	auto A = Mat22d::one();
	cout << Determinant(A) << endl;
	cout << Determinant(Mat22d()) << endl;
	A(0, 1) = 2;
	A(1, 0) = -2;
	cout << Determinant(A) << endl;
	return 0;
}